#ifndef MOCK_HELPER_H_
#define MOCK_HELPER_H_

#include <vector>

#include "dev_vga_fuzzer.h"

#define NO_THROW __attribute__((nothrow))


int pfnThreadDestroyNoop(PPDMTHREAD pThread, int *pRcThread) NO_THROW {
    return 0;
}

int pfnMmio2ControlDirtyPageTrackingNoop(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, bool fEnabled) NO_THROW {
    return 0;
}

int pfnPCIPhysReadNoop(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags) NO_THROW {
   // For this one not actually make a noop but plug in random data from the fuzzer.
   if (fuzzer == nullptr) {
       return 0;
   }
   std::vector<uint8_t> bytes = fuzzer->GetFdp()->ConsumeBytes<uint8_t>(cbRead);
   if (bytes.size() == 0) return 0;
   memcpy(pvBuf, bytes.data(), bytes.size());
   return 0;
}


int pfnPhysReadNoop(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags) NO_THROW {
   // For this one not actually make a noop but plug in random data from the fuzzer.
   if (fuzzer == nullptr) {
       return 0;
   }
   std::vector<uint8_t> bytes = fuzzer->GetFdp()->ConsumeBytes<uint8_t>(cbRead);
   if (bytes.size() == 0) return 0;
   memcpy(pvBuf, bytes.data(), bytes.size());
   return 0;
}


int pfnPhysWriteNoop(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags) NO_THROW {
    return 0;
}

int pfnSupSemEventSignalNoop(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent) NO_THROW {
    return 0;
}

int pfnPCIPhysWriteNoop(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags) NO_THROW {
    return 0;
}

int pfnCritSectEnterNoop(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy) NO_THROW {
    return 0;
}

int pfnCritSectLeaveNoop(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect) NO_THROW {
    return 0;
}


void pfnPCISetIrqNoop(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel) NO_THROW {
    return;
}


int pfnSUPSemEventCloseNoop(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent) NO_THROW {
    return 0;
}


int pfnScreenTargetBindNoop(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, uint32_t sid) NO_THROW {
    return 0;
}
int pfnScreenTargetUpdateNoop(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, SVGA3dRect const *pRect) NO_THROW {
    return 0;
}

#endif
